package yxy.game.pm2.bean;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import yxy.apple.util.redisson.RedisException;
import yxy.game.pm2.bean.currency.CurrencyAdditionException;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.currency.CurrencyType;

public class Currency {
    // bean===========================================================================
    private CurrencyType type;
    private int dataId;
    private long number;

    public CurrencyType getType() {
        return type;
    }

    public void setType(CurrencyType type) {
        this.type = type;
    }

    public int getDataId() {
        return dataId;
    }

    public void setDataId(int dataId) {
        this.dataId = dataId;
    }

    public long getNumber() {
        return number;
    }

    public void setNumber(long number) {
        this.number = number;
    }

    // func==========================================================================

    public String code() {
        String code = String.format("%d_%d", getType().getNumber(), getDataId() < 0 ? 0 : getDataId());
        return code;
    }

    // redis==========================================================================

    static public Currency create(int typeId, int dataId, long number) {
        CurrencyType type = CurrencyType.forNumber(typeId);
        if (type == null || number <= 0) {
            return null;
        }
        return create(type, dataId, number);
    }

    static public Currency create(CurrencyType type, int dataId, long number) {
        Currency currency = new Currency();
        currency.setType(type);
        currency.setDataId(dataId);
        currency.setNumber(number);
        return currency;
    }

    static public Collection<Currency> create(int[] typeIds, int[] dataIds, int[] nums) {
        List<Currency> list = new ArrayList<>();
        for (int i = 0; i < typeIds.length; i++) {
            Currency currency = create(typeIds[i], dataIds[i], nums[i]);
            if (currency != null) {
                list.add(currency);
            }
        }
        return list;
    }

    static public void add(String playerCode, Currency currency) throws CurrencyAdditionException, RedisException {
        if (currency == null || currency.getNumber() < 0) {
            throw new CurrencyAdditionException();
        }
        switch (currency.getType().getGroup()) {
            case ITEM:
                Item.add(playerCode, currency.getType(), currency.getDataId(), currency.getNumber());
                break;
            case POINT:
                Point.add(playerCode, currency.getType(), currency.getNumber());
                break;
            case SOUL:
                Soul.create(playerCode, currency.getDataId(), currency.getNumber());
                break;
            case SIGN:
                Sign.add(playerCode, currency.getType(), currency.getDataId());
                break;
            case PickedTroopsSlot:
                PickedTroopsSlot.create(playerCode, currency.getDataId(), currency.getNumber());
                break;
            default:
                break;
        }
    }

    static public long number(String playerCode, CurrencyType type, int dataId, Boolean isNewPlayer) {
        try {
            switch (type.getGroup()) {
                case HERO:
                    return Hero.getNumber(playerCode, dataId);
                case ITEM:
                    return Item.get(playerCode, type, dataId).getNumber();
                case POINT:
                    return Point.get(playerCode, type, isNewPlayer);
                case SOUL:
                    return Soul.getNumber(playerCode, dataId);
                case SIGN:
                    return Sign.exist(playerCode, type, dataId) ? 1 : 0;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 减少
     */
    static public void minus(String playerCode, CurrencyType type, int dataId, long number) throws CurrencyNotEnoughException {
        if (number <= 0) {
            return;
        }
        switch (type.getGroup()) {
            case HERO:
                Hero.minus(playerCode, dataId);
                break;
            case ITEM:
                Item.minus(playerCode, type, dataId, number);
                break;
            case POINT:
                Point.minus(playerCode, type, number);
                break;
            case SOUL:
                break;
            case SIGN:
                Sign.minus(playerCode, type, dataId);
                break;
            default:
                break;
        }
    }

    static public void minus(String playerCode, Currency... currencys) throws CurrencyNotEnoughException {
        ArrayList<Currency> list = new ArrayList<>();
        for (Currency currency : currencys) {
            if (currency == null) {
                continue;
            }
            list.add(currency);
        }
        minus(playerCode, list);
    }

    static public void minus(String playerCode, Collection<Currency> currencys) throws CurrencyNotEnoughException {
        // 合并
        currencys = merge(currencys);
        // 检查数量
        for (Currency currency : currencys) {
            if (currency == null) {
                continue;
            }
            long number = number(playerCode, currency.getType(), currency.getDataId(), false);
            if (currency.getNumber() > number) {
                throw new CurrencyNotEnoughException(currency.getType(), currency.getDataId());
            }
        }
        // 数量足够
        for (Currency currency : currencys) {
            minus(playerCode, currency.getType(), currency.getDataId(), currency.getNumber());
        }
    }

    static public boolean checkminus(String playerCode, Collection<Currency> currencys) throws CurrencyNotEnoughException {
        // 合并
        currencys = merge(currencys);
        // 检查数量
        for (Currency currency : currencys) {
            if (currency == null) {
                continue;
            }
            long number = number(playerCode, currency.getType(), currency.getDataId(), false);
            if (currency.getNumber() > number) {
                throw new CurrencyNotEnoughException(currency.getType(), currency.getDataId());
            }
        }
        return true;
    }

    /**
     * 合并
     */
    static public Collection<Currency> merge(Collection<Currency> currencys) {
        HashMap<String, Currency> cmap = new HashMap<>();
        for (Currency currency : currencys) {
            if (currency == null) {
                continue;
            }
            String code = currency.code();
            if (!cmap.containsKey(code)) {
                cmap.put(code, Currency.create(currency.getType(), currency.getDataId(), currency.getNumber()));
                continue;
            }
            Currency temp = cmap.get(code);
            temp.setNumber(temp.getNumber() + currency.getNumber());
        }
        return cmap.values();
    }

    @Override
    public String toString() {
        return String.format("%s:%s:%s", getType().name(), getDataId(), getNumber());
    }
}
